package com.thssh.ui.lsn03.view;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

/**
 * 圆形进度条
 *
 * @author zhangyugehu
 * @version V1.0
 * @date 2017/09/11
 * email: zhangyugehu@163.com
 */

public class CircleProgressView extends View {

    interface State{
        int WAITING = 0;
        int PROGRESSING = 1;
        int COMPLETED = 2;
        int ERROR = 3;
    }

    private static final int DEF_STATE = State.WAITING;

    private Paint mWaitingPaint;
    private Paint mProgressPaint;
    private Paint mTextPaint;

    private ValueAnimator mWaitingAnimator;

    private int mState;
    private int mWidth = 200;
    private int mHeight = 200;
    private int mStart;

    /** 进度百分百 */
    private int mPresent;

    public CircleProgressView(Context context) {
        this(context, null);
    }

    public CircleProgressView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mWaitingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mState = DEF_STATE;
        mWaitingAnimator = ValueAnimator.ofInt(0, 365);
        mWaitingAnimator.setDuration(365 * 10);
        mWaitingAnimator.setRepeatCount(ValueAnimator.INFINITE);
        mWaitingAnimator.setRepeatMode(ValueAnimator.RESTART);
        mWaitingAnimator.setInterpolator(new LinearInterpolator());
        mWaitingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mStart = (int) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        startWaitingAnimation();
    }

    private void startWaitingAnimation() {
        if(mWaitingAnimator != null) { mWaitingAnimator.start(); }
    }

    private void stopWaitingAnimation() {
        if(mWaitingAnimator != null) { mWaitingAnimator.cancel(); }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(mWidth, mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int radius = Math.min(mWidth, mHeight) / 2;
        switch (mState){
            case State.PROGRESSING:
                drawProgressCircle(mWidth / 2, mHeight / 2, radius, canvas);
                drawTextProgress(radius, canvas);
                break;
            case State.COMPLETED:
                drawCompleted();
                break;
            case State.ERROR:
                break;
            case State.WAITING:
            default:
                drawWaitingCircle(mWidth / 2, mHeight / 2, radius, canvas);
                break;
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        stopWaitingAnimation();
    }

    private void drawCompleted() {

    }

    private void drawTextProgress(int radius, Canvas canvas) {
        mTextPaint.setAlpha(255 / 3);
        mTextPaint.setColor(Color.BLUE);
        mTextPaint.setTextSize(80);
        drawTextByCenter(mPresent + "%", radius, radius, mTextPaint, canvas);
    }

    private void drawProgressCircle(int x, int y, int radius, Canvas canvas) {
        mProgressPaint.setStyle(Paint.Style.STROKE);
        mProgressPaint.setStrokeCap(Paint.Cap.BUTT);
        mProgressPaint.setStrokeWidth(10);

        radius -= 10;
        int left = x - radius;
        int top = y - radius;
        int right = left + radius * 2;
        int bottom = top + radius * 2;
        RectF oval = new RectF(left, top, right, bottom);
        mProgressPaint.setColor(Color.GRAY);
        canvas.drawCircle(x, y, radius, mProgressPaint);
        mProgressPaint.setColor(Color.BLUE);
        canvas.drawArc(oval, -90, 360 * mPresent / 100, false, mProgressPaint);
    }

    private void drawWaitingCircle(int x, int y, int radius, Canvas canvas) {
        mWaitingPaint.setStyle(Paint.Style.STROKE);
        mWaitingPaint.setStrokeCap(Paint.Cap.BUTT);
        mWaitingPaint.setColor(Color.WHITE);
        mWaitingPaint.setStrokeWidth(10);
        radius -= 10;
        mWaitingPaint.setColor(Color.BLUE);
        int left = x - radius;
        int top = y - radius;
        int right = left + radius * 2;
        int bottom = top + radius * 2;
        RectF oval = new RectF(left, top, right, bottom);
        canvas.drawArc(oval, mStart, 330, false, mWaitingPaint);
    }

    // 根据文字的中心轴来添加文本
    private void drawTextByCenter(String text, int x, int centerY, Paint paint, Canvas canvas) {
        canvas.save();

        Paint.FontMetricsInt fmi = mTextPaint.getFontMetricsInt();
        int baseLineY = centerY - (fmi.top + fmi.bottom) / 2;
        float width = mTextPaint.measureText(text);
//        int startX = (int) (x - width / 2);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText(text, x, baseLineY, paint);

        canvas.restore();
    }

    // ****
    /**
     * [0...100]
     * @param progress
     */
    public void setProgress(int progress){
        this.mPresent = progress;
        if(progress > 99){
            mState = State.COMPLETED;
        }
        postInvalidate();
    }

    public void showWaiting(){
        this.mState = State.WAITING;
        startWaitingAnimation();
        postInvalidate();
    }

    public void showProgress(){
        this.mState = State.PROGRESSING;
        stopWaitingAnimation();
        postInvalidate();
    }

    public void showError(){
        // TODO 实现错误状态展示
        this.mState = State.ERROR;
        stopWaitingAnimation();
        postInvalidate();
    }
}
